package aliyun

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gylang/aliyun/webdav/aliyun/model/req"
	"github.com/gylang/aliyun/webdav/aliyun/model/res"
	"github.com/gylang/aliyun/webdav/conf"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

const (
	FileList = "https://api.aliyundrive.com/adrive/v3/file/list"
	// FilePath req {"drive_id":"95850361","file_id":"61000cb39b0d03de1fce4117b9f50329f827078b"}
	// FilePath res {"items":[{"created_at":"2021-07-27T13:40:03.645Z","domain_id":"bj29","drive_id":"95850361","encrypt_mode":"none","file_id":"61000cb39b0d03de1fce4117b9f50329f827078b","hidden":false,"name":"auto-wallpaper","parent_file_id":"root","starred":false,"status":"available","type":"folder","updated_at":"2021-09-11T07:51:14.139Z","user_meta":"{\"shares\":[\"DkTpjkkfjvw\"]}"}]}
	FilePath = "https://api.aliyundrive.com/adrive/v1/file/get_path"
	// File req {"drive_id":"95850361","file_id":"613f57decde6d660fe324faaabca122b5e6d0ca9"}
	// File res {"drive_id":"95850361","domain_id":"bj29","file_id":"613f57decde6d660fe324faaabca122b5e6d0ca9","name":"软件","type":"folder","created_at":"2021-09-13T13:53:34.127Z","updated_at":"2021-09-13T13:53:34.127Z","hidden":false,"starred":false,"status":"available","parent_file_id":"root","encrypt_mode":"none","trashed":false}
	File = "https://api.aliyundrive.com/v2/file/get"
	// FileDownloadUrl req {"drive_id":"95850361","file_id":"613a107eb210a9a066cb4f518d98cef762323774"}
	// FileDownloadUrl res {"method":"GET","url":"https://bj29.cn-beijing.data.alicloudccp.com/5fb4619d8d37a4bdcc7c48b4b0123ff397dae04b%2F5fb4619d07d8190cad63462f97c5d70026666ad9?di=bj29&dr=95850361&f=613a107eb210a9a066cb4f518d98cef762323774&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27vc_redist.x64.exe&u=4eb26411a9b74e2bbca0347b56401309&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-additional-headers=referer&x-oss-expires=1631542161&x-oss-signature=AAezPjlGzdAlrPkUbIEviCfwZGbNdL72WUMQulsUx%2Bo%3D&x-oss-signature-version=OSS2","internal_url":"http://ccp-bj29-bj-1592982087.oss-cn-beijing-internal.aliyuncs.com/5fb4619d8d37a4bdcc7c48b4b0123ff397dae04b%2F5fb4619d07d8190cad63462f97c5d70026666ad9?di=bj29&dr=95850361&f=613a107eb210a9a066cb4f518d98cef762323774&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%27vc_redist.x64.exe&u=4eb26411a9b74e2bbca0347b56401309&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-additional-headers=referer&x-oss-expires=1631542161&x-oss-signature=AAezPjlGzdAlrPkUbIEviCfwZGbNdL72WUMQulsUx%2Bo%3D&x-oss-signature-version=OSS2","cdn_url":"","expiration":"2021-09-13T14:09:21.215Z","size":15301888,"ratelimit":{"part_speed":-1,"part_size":-1}}
	FileDownloadUrl = "https://api.aliyundrive.com/v2/file/get_download_url"
	// CreateFolder req {"drive_id":"95850361","parent_file_id":"root","name":"软件","check_name_mode":"refuse","type":"folder"}
	// CreateFolder res {"parent_file_id":"root","type":"folder","file_id":"613f57decde6d660fe324faaabca122b5e6d0ca9","domain_id":"bj29","drive_id":"95850361","file_name":"软件","encrypt_mode":"none"}
	CreateFolder = "https://api.aliyundrive.com/adrive/v2/file/createWithFolders"
	// Rename req {"drive_id":"95850361","file_id":"613f58c112ba625c14824874b5ab0c5f02f518f4","name":"22.bash_history","check_name_mode":"refuse"}
	// Rename res {"drive_id":"95850361","domain_id":"bj29","file_id":"613f58c112ba625c14824874b5ab0c5f02f518f4","name":"22.bash_history","type":"file","content_type":"application/oct-stream","created_at":"2021-09-13T13:57:21.117Z","updated_at":"2021-09-13T13:59:26.786Z","file_extension":"bash_history","hidden":false,"size":448,"starred":false,"status":"available","upload_id":"CC74D96F24CF49D5812576A3311031E9","parent_file_id":"61000cb39b0d03de1fce4117b9f50329f827078b","crc64_hash":"18363704050137254359","content_hash":"53A085CB7D5E91722352A178E006B4CE86C31826","content_hash_name":"sha1","download_url":"https://bj29.cn-beijing.data.alicloudccp.com/JW5FSrj2%2F95850361%2F613f58c112ba625c14824874b5ab0c5f02f518f4%2F613f58c167ea4d7e73f341c695f350e97eeb9c69?di=bj29&dr=95850361&f=613f58c112ba625c14824874b5ab0c5f02f518f4&response-content-disposition=attachment%3B%20filename%2A%3DUTF-8%27%2722.bash_history&u=4eb26411a9b74e2bbca0347b56401309&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-additional-headers=referer&x-oss-expires=1631542466&x-oss-signature=W9SCgTgF%2BSF0o%2FjF8RKHTrjzIOkzwUh4paihNqgTFIc%3D&x-oss-signature-version=OSS2","url":"https://bj29.cn-beijing.data.alicloudccp.com/JW5FSrj2%2F95850361%2F613f58c112ba625c14824874b5ab0c5f02f518f4%2F613f58c167ea4d7e73f341c695f350e97eeb9c69?di=bj29&dr=95850361&f=613f58c112ba625c14824874b5ab0c5f02f518f4&u=4eb26411a9b74e2bbca0347b56401309&x-oss-access-key-id=LTAIsE5mAn2F493Q&x-oss-additional-headers=referer&x-oss-expires=1631542466&x-oss-signature=Fd%2FBvfccGjasyrjhVVS6xqJeXHU4WUMvjXkDB2rN10I%3D&x-oss-signature-version=OSS2","category":"others","encrypt_mode":"none","punish_flag":0,"trashed":false}
	Rename = "https://api.aliyundrive.com/v3/file/update"

	// Move req {"requests":[{"body":{"drive_id":"95850361","file_id":"61000cb3f6b43cab0e6f4ca797c88f6738979986","to_drive_id":"95850361","to_parent_file_id":"61000cb75387367f130240b5ab3bf8827b30b038"},"headers":{"Content-Type":"application/json"},"id":"61000cb3f6b43cab0e6f4ca797c88f6738979986","method":"POST","url":"/file/move"}],"resource":"file"}
	// Move req {"responses":[{"body":{"domain_id":"bj29","drive_id":"95850361","file_id":"61000cb3f6b43cab0e6f4ca797c88f6738979986"},"id":"61000cb3f6b43cab0e6f4ca797c88f6738979986","status":200}]}
	Move = "https://api.aliyundrive.com/v3/batch"
	// Remove req https://api.aliyundrive.com/v2/recyclebin/trash  {"drive_id":"95850361","file_id":"61527aaf55df3b7778814580b307e1f119bf7864"}
	// Remove res {"domain_id":"bj29","drive_id":"95850361","file_id":"61527aaf55df3b7778814580b307e1f119bf7864","async_task_id":"61527aaf55df3b7778814580b307e1f119bf7864trash2699b40fa6134f7c96a0ff706b2d23ef"}
	Remove = "https://api.aliyundrive.com/v3/batch"
)

var auth = ""

//Post 直接发起请求
func Post(url string, body interface{}) ([]byte, error) {
	bs, _ := json.Marshal(body)
	request := createAliRequest()
	request.Method = "POST"
	request.Header.Set("contentType", "application/json")
	WriteUrl(url, request)
	WriteBody(bs, request)
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	} else {
		if bodyBytes, err := io.ReadAll(response.Body); err != nil {
			return nil, err
		} else {
			return bodyBytes, nil
		}
	}
}

// Executor  直接发起请求
func Executor(r *http.Request) ([]byte, error) {
	response, err := http.DefaultClient.Do(r)
	if err != nil {
		return nil, err
	} else {
		if bodyBytes, err := io.ReadAll(response.Body); err != nil {
			return nil, err
		} else {
			return bodyBytes, nil
		}
	}
}

// DoPost  发起请求
func DoPost(url string, body interface{}) ([]byte, error) {
	bs, _ := json.Marshal(body)
	request := createAliRequest()
	request.Method = "POST"
	request.Header.Set("contentType", "application/json")
	WriteUrl(url, request)
	WriteBody(bs, request)
	response, err := http.DefaultClient.Do(request)
	if err != nil || response.StatusCode != 200 {

		return errorHandler(response, func() ([]byte, error) {
			return DoPost(url, body)
		})
	} else {
		if bodyBytes, err := io.ReadAll(response.Body); err != nil {
			return nil, err
		} else {
			return bodyBytes, nil
		}
	}
}

//createAliRequest 创建基本请求对象
func createAliRequest() *http.Request {
	header := http.Header{}
	header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36")
	header.Set("origin", "https://www.aliyundrive.com")
	header.Set("referer", "https://www.aliyundrive.com/")
	header.Set("authorization", auth)
	request := http.Request{Header: header}
	return &request
}

//errorHandler 处理响应异常
func errorHandler(response *http.Response, retry func() ([]byte, error)) ([]byte, error) {

	body := response.Body
	if response.StatusCode == 401 && body != nil {
		// 刷新token处理
		bs, err := io.ReadAll(body)
		if err != nil {
			return nil, err
		} else {
			body := string(bs)
			if strings.Contains(body, "refresh_token") {
				// 刷新token 重新发起
				if retry != nil {
					if refreshToken() == nil {
						return retry()
					}
				}
			}
		}
	}
	return nil, fmt.Errorf("无法处理异常")
}

//refreshToken 刷新token异常
func refreshToken() error {
	rf, err := conf.RefreshTokenFromDisk()
	if err != nil {
		return err
	}
	body, err := Post("https://websv.aliyundrive.com/token/refresh", map[string]string{"refresh_token": rf})
	if err != nil {
		return err
	}
	result := map[string]string{}
	err = json.Unmarshal(body, &result)
	if err != nil {
		return err
	}
	// 写入token refresh_token
	accessToken := result["access_token"]
	conf.AliConfSet.Authorization = accessToken
	refreshToken := result["refresh_token"]
	conf.AliConfSet.RefreshToken = refreshToken
	return nil
}

//WriteBody 将请求体写入到request
func WriteBody(bs []byte, client *http.Request) {

	readCloser := ioutil.NopCloser(bytes.NewReader(bs))
	client.Body = readCloser
}

//WriteUrl 写入请求url
func WriteUrl(urlStr string, r *http.Request) {

	u, _ := url.Parse(urlStr)
	r.URL = u
}

func Download(urlStr string, r *http.Request, size int64) ([]byte, error) {

	request := createAliRequest()

	rangeStr := r.Header.Get("range")
	if len(rangeStr) > 0 {
		// 如果range最后 >= size， 则去掉
		rangeArr := strings.Split(rangeStr, "-")
		if len(rangeArr) == 2 {
			end := rangeArr[1]
			endInt, err := strconv.ParseInt(end, 10, 64)
			if err != nil {
				return nil, err
			}
			if endInt >= size {
				rangeStr = rangeStr[:strings.LastIndex(rangeStr, "-")+1]
			}
		}
		request.Header.Set("range", rangeStr)
	}

	ifRange := r.Header.Get("if-range")
	if len(ifRange) > 0 {
		request.Header.Set("if-range", ifRange)
	}
	WriteUrl(urlStr, request)
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	} else {
		if bodyBytes, err := io.ReadAll(response.Body); err != nil {
			return nil, err
		} else {
			return bodyBytes, nil
		}
	}
}

func DoGet(urlStr string, params map[string]string) ([]byte, error) {
	request := createAliRequest()
	request.Method = "GET"
	u, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}
	if len(params) > 0 {
		for k, v := range params {
			u.Query().Set(k, v)
		}
	}
	request.URL = u
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	} else {
		if bodyBytes, err := io.ReadAll(response.Body); err != nil {
			return nil, err
		} else {
			return bodyBytes, nil
		}
	}
}

func DoDownload(filePath string, r *http.Request, size int64) ([]byte, error) {

	tFile := GetFileFromFileCache(filePath)
	if tFile == nil {
		return nil, fmt.Errorf("文件不存在: %s", filePath)
	}
	// 调用获取请求连接方法
	downloadURL := req.DownloadURL{ExpireSec: 14400, DriveID: conf.AliConfSet.DriveId, FileID: tFile.FileId}
	bs, err := DoPost(FileDownloadUrl, downloadURL)
	if err != nil {
		return nil, err
	}
	downloadURLRes := res.DownloadURLRes{}
	err = json.Unmarshal(bs, &downloadURLRes)
	if err != nil {
		return nil, err
	}
	return Download(downloadURLRes.URL, r, size)
}

func Upload(url string, bs []byte, offset int, byteCount int) error {

	if (offset|len(bs)) < 0 || offset > len(bs) || len(bs)-offset < byteCount {
		return fmt.Errorf("数据越界, 上传失败")
	}
	bs = bs[offset : offset+byteCount]
	request := createAliRequest()
	WriteUrl(url, request)
	WriteBody(bs, request)
	bs, err := Executor(request)
	return err
}
